﻿/***************************************************************
 * 开发人员：网魂小兵@http://www.mozlite.com
 * 
 * 目标标本：4.0.30319.239
 * 
 * 最后修改：2011/11/2 13:57:58
 * ************************************************************/
namespace Mozlite
{
    using System;
    using System.Linq;
    using System.Text;
    using System.Collections.Generic;
    using System.Globalization;
    using Mozlite.Common.Configuration;
    using System.IO;
    using System.Xml.XPath;
    using Mozlite.Common;
    using System.Threading;

    /// <summary>
    /// 资源管理类。
    /// </summary>
    public class Resources
    {
        /// <summary>
        /// 获取所有支持的资源（键为编程言语名称：zh-cn）。
        /// </summary>
        /// <param name="areaName">区域名称。</param>
        /// <returns>返回支持资源列表。</returns>
        public static Dictionary<string, CultureInfo> GetSupportLanagues(string areaName = null)
        {

            string cacheKey = string.Format("Resources::SupportLanagues.{0}", areaName);
            string path = GetDirectory(areaName);
            return Caches.Get<Dictionary<string, CultureInfo>>(cacheKey, () =>
            {
                var resources = new Dictionary<string, CultureInfo>(StringComparer.OrdinalIgnoreCase);
                var root = new DirectoryInfo(path);
                if (root.Exists)
                {
                    foreach (var directory in root.GetDirectories())
                    {
                        try
                        {
                            resources.Add(directory.Name, CultureInfo.CreateSpecificCulture(directory.Name));
                        }
                        catch { }
                    }
                }
                return Caches.Max(cacheKey, resources);
            });
        }

        private static string GetDirectory(string areaName)
        {
            if (areaName == null)
                return CommonHelper.MapPath("~/Resources/");
            return CommonHelper.MapPath("~/Areas/" + areaName + "/Resources/");
        }
        /// <summary>
        /// 获取资源字符串。
        /// </summary>
        /// <param name="key">资源键，如果是枚举将以“Type_Property”出现。</param>
        /// <param name="defaultValue">默认值。</param>
        /// <returns>返回资源字符串。</returns>
        public static string GetString(object key, string controller = null, string areaName = null)
        {
            return GetString(key, Culture.Name, controller, areaName);
        }
        /// <summary>
        /// 获取资源字符串。
        /// </summary>
        /// <param name="key">资源键。</param>
        /// <param name="controller">控制器。</param>
        /// <param name="areaName">区域。</param>
        /// <returns>返回资源字符串。</returns>
        public static string GetString(string key, string controller = null, string areaName = null)
        {
            return GetString(key, Culture.Name, controller, areaName);
        }
        /// <summary>
        /// 获取资源字符串。
        /// </summary>
        /// <param name="key">资源键，如果是枚举将以“Type_Property”出现。</param>
        /// <param name="language">语言。</param>
        /// <param name="defaultValue">默认值。</param>
        /// <returns>返回资源字符串。</returns>
        public static string GetString(object key, string language, string controller = null, string areaName = null)
        {
            string name = key.ToString();
            if (key.GetType().IsEnum)
                name = key.GetType().Name + "." + name;
            return GetString(name, language, controller, areaName);
        }
        /// <summary>
        /// 获取资源字符串。
        /// </summary>
        /// <param name="key">资源键。</param>
        /// <param name="language">语言。</param>
        /// <param name="controller">控制器。</param>
        /// <param name="areaName">区域。</param>
        /// <returns>返回资源字符串。</returns>
        public static string GetString(string key, string language, string controller = null, string areaName = null)
        {
            string value;
            if (language != null && GetSupportLanagues(areaName).ContainsKey(language))
            {
                value = GetControllerResource(key, language, controller, areaName);
                if (value != null)
                    return value;
            }
            if (!language.IsMatched(SiteSettings.Current.Language))
            {
                value = GetControllerResource(key, SiteSettings.Current.Language, controller, areaName);
                if (value != null)
                    return value;
            }
            if (!"zh-cn".IsMatched(SiteSettings.Current.Language) && !language.IsMatched("zh-cn"))
            {
                value = GetControllerResource(key, "zh-cn", controller, areaName);
                if (value != null)
                    return value;
            }
            var ex = new Exception(string.Format("资源不存在（键：{0}，语言：{1},控制器：{2},区域：{3}）！", key, language, controller, areaName));
#if DEBUG
            throw ex;
#else
            Logs.Warn("ResourceKeyNotFound:", "Resources", EventID.Resource, ex, "Resources");
            return key;
#endif
        }

        private static string GetControllerResource(string key, string language, string controller, string areaName)
        {
            string value;
            if (controller != null)
            {
                controller += ".controller";
                var cresources = LoadFromCacheOrFile(language, controller, areaName);
                if (cresources != null && cresources.TryGetValue(key, out value))
                    return value;
            }

            var resources = LoadFromCacheOrFile(language, "languages", areaName);
            if (resources != null && resources.TryGetValue(key, out value))
                return value;

            return null;
        }

        private static Dictionary<string, string> LoadFromCacheOrFile(string language, string resourceName/*资源文件名*/, string areaName = null)
        {
            string path = Globals.Combine(GetDirectory(areaName), language + "/" + resourceName + ".resx", true);
            if (File.Exists(path))
            {
                string key = string.Format("Resources::Languages::{0}::{1}::{2}", language, resourceName, areaName);
                return Caches.Get<Dictionary<string, string>>(key, () =>
                {
                    var resources = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
                    var doc = new XPathDocument(path);
                    resources = new Dictionary<string, string>();
                    foreach (XPathNavigator nav in doc.CreateNavigator().Select("root/data"))
                    {
                        if (nav.NodeType != XPathNodeType.Comment)
                        {
                            resources[nav.GetAttribute("name", string.Empty)] = nav.SelectSingleNode("value").Value;
                        }
                    }
                    if (SiteSettings.Current.Language.IsMatched(language))
                        Caches.Max(key, resources, new System.Web.Caching.CacheDependency(path));
                    else
                        Caches.Insert(key, resources, new System.Web.Caching.CacheDependency(path));
                    return resources;
                });
            }
            return null;
        }
        /// <summary>
        /// 格式化获取字符串。
        /// </summary>
        /// <param name="key">资源键。</param>
        /// <param name="controller">控制器。</param>
        /// <param name="areaName">区域名称。</param>
        /// <param name="args">参数。</param>
        /// <returns>返回资源字符串。</returns>
        public static string GetString(string key, string controller, string areaName, params object[] args)
        {
            return string.Format(GetString(key, controller, areaName), args);
        }
        /// <summary>
        /// 格式化获取字符串。
        /// </summary>
        /// <param name="key">资源键。</param>
        /// <param name="controller">控制器。</param>
        /// <param name="areaName">区域名称。</param>
        /// <param name="args">参数。</param>
        /// <returns>返回资源字符串。</returns>
        public static string GetString(object key, string controller, string areaName, params object[] args)
        {
            return string.Format(GetString(key, controller, areaName), args);
        }

        /// <summary>
        /// 设置言语区域。
        /// </summary>
        /// <param name="language">当前语言。</param>
        public static void SetCulture(string language = null)
        {
            if (language != null)
            {
                System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(language);
                System.Threading.Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(language);
            }
        }
        /// <summary>
        /// 当前区域文化信息。
        /// </summary>
        public static CultureInfo Culture
        {
            get
            {
                return CultureInfo.CreateSpecificCulture(SiteSettings.Current.Language);
            }
        }
    }
}